package org.dromara.system.kernel;

import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.domain.bo.PayOrderBo;
import org.dromara.system.elastic.EsQueryType;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.UpdateQuery;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单搜索核心处理
 */
@RefreshScope
@Service
@RequiredArgsConstructor
public class OrderSearchKernel {

    private final ElasticsearchTemplate restTemplate;
    private final RestHighLevelClient restHighLevelClient;
    @Value("${spring.elasticsearch.environment}")
    private String environment;
    @Value("${hideOrder}")
    public Boolean hideOrder;


    public <O> PageImpl<O> queryOrderEsPage(QueryBuilder queryBuilder, Integer pageNum, Integer pageSize, Class<O> clazz, List<SortBuilder<?>> sorts, String... fields) {

        if (sorts == null || sorts.isEmpty()) {
            sorts = new ArrayList<>();
            sorts.add(SortBuilders.fieldSort("isDelete").order(SortOrder.ASC));
            sorts.add(SortBuilders.fieldSort("createTime").order(SortOrder.DESC));
        }

        try {
            //查询总数
            CountRequest countRequest = new CountRequest("pay_order_" + environment);
            countRequest.source(SearchSourceBuilder.searchSource().query(queryBuilder));
            CountResponse countResponse = restHighLevelClient.count(countRequest, RequestOptions.DEFAULT);


            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            //设置查询条件
            searchSourceBuilder.query(queryBuilder);
            // 指定返回的字段
            if (fields != null && fields.length > 0) {
                searchSourceBuilder.fetchSource(fields, null);
            }
            //排序
            if (!sorts.isEmpty()) {
                searchSourceBuilder.sort(sorts);
            }

            // 不分页  封装查询结果
            if (pageNum == null || pageSize == null) {
                int batchSize = 3000; // 每次查询的数据条数
                int totalCount = (int) countResponse.getCount();
                int totalBatches = (int) Math.ceil((double) totalCount / batchSize);
                List<O> allResults = new ArrayList<>();

                for (int i = 0; i < totalBatches; i++) {
                    int start = i * batchSize;
                    int size = Math.min(batchSize, totalCount - start);
                    searchSourceBuilder.size(size).from(start);
                    SearchRequest searchRequest = new SearchRequest("pay_order_" + environment);
                    searchRequest.source(searchSourceBuilder);
                    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

                    List<O> batchResults = Arrays.stream(searchResponse.getHits().getHits()).map(hit -> JSONObject.parseObject(hit.getSourceAsString(), clazz)).toList();

                    allResults.addAll(batchResults);
                }

                PageRequest pageRequest = PageRequest.of(0, Integer.MAX_VALUE);
                return new PageImpl<>(allResults, pageRequest, totalCount);
            }

            //分页
            searchSourceBuilder.from(pageNum * pageSize);
            searchSourceBuilder.size(pageSize);

            SearchRequest searchRequest = new SearchRequest("pay_order_" + environment);
            searchRequest.source(searchSourceBuilder);
            SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

            List<O> content = Arrays.stream(searchResponse.getHits().getHits()).map(hit -> JSONObject.parseObject(hit.getSourceAsString(), clazz)).collect(Collectors.toList());
            return new PageImpl<>(content, PageRequest.of(pageNum, pageSize), countResponse.getCount());
        } catch (IOException e) {
            e.printStackTrace();
            return new PageImpl<>(new ArrayList<>(), PageRequest.of(pageNum, pageSize), 0);
        }
    }

    public QueryBuilder buildQueryBuilder(PayOrderBo bo) {
        //可见权限
        if (LoginHelper.isAgent()) {
            bo.setAgentId(LoginHelper.getUserId());
        }
        else if (LoginHelper.isSupplier()) {
            bo.setSupplierId(LoginHelper.getUserId());
        }
        else if (LoginHelper.isManager()) {
            bo.setManagerId(LoginHelper.getUserId());
        }
        else if (LoginHelper.isService()) {
            String accountIds = LoginHelper.getLoginUser().getAccountIds();
            //如果传了账号ID，就只查询这些账号ID的订单
            if (StringUtils.isNotBlank(bo.getAccountIds())) {
                List<String> haveAccounts = Arrays.stream(accountIds.split(",")).toList();
                accountIds = Arrays.stream(bo.getAccountIds().split(",")).filter(haveAccounts::contains).collect(Collectors.joining(","));
            }
            if (StringUtils.isNotBlank(accountIds)) {
                bo.setAccountIds(accountIds);
            } else {
                bo.setClientId(LoginHelper.getUserId());
            }
        }
        else if (!LoginHelper.isSuperAdmin()) {
            bo.setClientId(LoginHelper.getUserId());
        }

        //构建查询条件
        BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        try {
            Field[] fields = bo.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true); // 允许访问私有字段
                Object value = field.get(bo); // 获取字段值

                if (value == null) {
                    continue;
                }

                String fieldName = field.getName(); // 获取字段名
                Class<?> fieldType = field.getType(); // 获取字段类型

                // 根据字段类型构建查询条件
                if (fieldType == String.class) {
                    EsQueryType esQueryType = field.getAnnotation(EsQueryType.class);
                    String valStr = (String) value;

                    if (esQueryType == null) {
                        queryBuilder.filter(new TermQueryBuilder(fieldName, valStr));
                        continue;
                    }

                    if (StringUtils.isNotBlank(esQueryType.field())) {
                        fieldName = esQueryType.field();
                    }

                    switch (esQueryType.type()) {
                        case KEYWORD:
                            queryBuilder.filter(new TermQueryBuilder(fieldName + ".keyword", valStr));
                            break;
                        case LIKE:
                            // 模糊查询 WildcardQueryBuilder  MatchQueryBuilder
                            queryBuilder.filter(new MatchQueryBuilder(fieldName, "*" + valStr + "*"));
                            break;
                        case IN:
                            // 模糊查询
                            queryBuilder.filter(new TermsQueryBuilder(fieldName, Arrays.stream(valStr.split(",")).peek(Integer::parseInt).collect(Collectors.toSet())));
                            break;
                        default:
                            queryBuilder.filter(new TermQueryBuilder(fieldName, valStr));
                    }
                } else if (fieldType == Integer.class || fieldType == Long.class) {
                    //处理供应商状态查询
                    if (fieldName.equals("status") && LoginHelper.isSupplier()) {
                        if (Objects.equals(value, 2)) {
                            // 查询 status = 2 或者 isFeign = 1 的
                            queryBuilder.filter(
                                QueryBuilders.boolQuery()
                                    .should(QueryBuilders.termQuery("status", 2)) // status = 2
                                    .should(QueryBuilders.termQuery("isFeign", 1)) // isFeign = 1
                                    .minimumShouldMatch(1) // 至少满足一个条件（OR 查询）
                            );
                            continue;
                        } else if (Objects.equals(value, 3)) {
                            // 查询 status = 3 并且 isFeign = 0 的
                            queryBuilder.filter(
                                QueryBuilders.boolQuery()
                                    .must(QueryBuilders.termQuery("status", 3)) // status = 3
                                    .must(QueryBuilders.termQuery("isFeign", 0)) // isFeign = 0
                            );
                            continue;
                        }
                    }

                    queryBuilder.filter(new TermQueryBuilder(fieldName, value));
                }
//                else if (fieldType == Collections.class) {
//                    queryBuilder.filter(new TermsQueryBuilder(fieldName, value));
//                }
            }
        } catch (Exception ignore) {
        }

        //处理日期范围查询
        Map<String, Object> params = bo.getParams();
        if (params != null) {
            try {

                if (params.containsKey("minMoney") && params.containsKey("maxMoney")) {
                    Object minMoney = params.get("minMoney");
                    Object maxMoney = params.get("maxMoney");
                    RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("usdMoney");
                    rangeQueryBuilder.gte(minMoney);
                    rangeQueryBuilder.lte(maxMoney);
                    queryBuilder.filter(rangeQueryBuilder);
                }

                SimpleDateFormat sdfEnd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 定义结束日期格式

                if (params.containsKey("beginPayTime") && params.containsKey("endPayTime")) {
                    Date beginPayTime = sdfEnd.parse(params.get("beginPayTime").toString());
                    Date endPayTime = sdfEnd.parse(params.get("endPayTime").toString());
                    RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("payTime");
                    rangeQueryBuilder.gte(beginPayTime.getTime());
                    rangeQueryBuilder.lte(endPayTime.getTime());
                    queryBuilder.filter(rangeQueryBuilder);
                }

                if (params.containsKey("beginUpdateTime") && params.containsKey("endUpdateTime")) {
                    Date beginUpdateTime = sdfEnd.parse(params.get("beginUpdateTime").toString());
                    Date endUpdateTime = sdfEnd.parse(params.get("endUpdateTime").toString());
                    RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("updateTime");
                    rangeQueryBuilder.gte(beginUpdateTime.getTime());
                    rangeQueryBuilder.lte(endUpdateTime.getTime());
                    queryBuilder.filter(rangeQueryBuilder);
                }

                if (params.containsKey("beginCreateTime") && params.containsKey("endCreateTime")) {
                    Date beginCreateTime = sdfEnd.parse(params.get("beginCreateTime").toString());
                    Date endCreateTime = sdfEnd.parse(params.get("endCreateTime").toString());
                    RangeQueryBuilder rangeQueryBuilder = new RangeQueryBuilder("createTime");
                    rangeQueryBuilder.gte(beginCreateTime.getTime());
                    rangeQueryBuilder.lte(endCreateTime.getTime());
                    queryBuilder.filter(rangeQueryBuilder);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        //商户不看创建失败订单
        if (LoginHelper.isClient()) {
            queryBuilder.mustNot(QueryBuilders.termQuery("status", 0));
        }

        //不指定状态时，不可见暂存订单
        if (bo.getStatus() == null) {
            queryBuilder.mustNot(QueryBuilders.termQuery("status", -1));
        }

        //隐藏订单
        if (!LoginHelper.isSuperAdmin() && hideOrder) {
            queryBuilder.mustNot(QueryBuilders.termQuery("hide", 1));
        }

        return queryBuilder;
    }


    public SearchResponse highLevelSearchOrder(SearchSourceBuilder searchSourceBuilder) {
        try {
            searchSourceBuilder.fetchSource(false); // 关闭文档的源数据检索
            SearchRequest searchRequest = new SearchRequest("pay_order_" + environment); //索引名
            searchRequest.source(searchSourceBuilder);
            return restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public SearchResponse search(SearchRequest searchRequest) {
        try {
            return restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    public void bulkUpdate(List<UpdateQuery> queries) {
        try {
            restTemplate.bulkUpdate(queries, IndexCoordinates.of("pay_order_" + environment));
        } catch (Exception e) {
            if (e.getMessage() == null || !e.getMessage().contains("200 OK")) {
                e.printStackTrace();
            }
        }
    }
}
